#pragma once

#include "deviceManager.hpp"
#include "mqttClient.hpp"
#include <string>

namespace Protocol {

inline nlohmann::json any_to_json(const std::any &v) {
    if (v.type() == typeid(uint8_t)) {
        return std::any_cast<uint8_t>(v);
    } else if (v.type() == typeid(uint16_t)) {
        return std::any_cast<uint16_t>(v);
    } else if (v.type() == typeid(uint32_t)) {
        return std::any_cast<uint32_t>(v);
    } else if (v.type() == typeid(uint64_t)) {
        return std::any_cast<uint64_t>(v);
    } else if (v.type() == typeid(int8_t)) {
        return std::any_cast<int8_t>(v);
    } else if (v.type() == typeid(int16_t)) {
        return std::any_cast<int16_t>(v);
    } else if (v.type() == typeid(int32_t)) {
        return std::any_cast<int32_t>(v);
    } else if (v.type() == typeid(int64_t)) {
        return std::any_cast<int64_t>(v);
    } else if (v.type() == typeid(std::string)) {
        return std::any_cast<std::string>(v);
    } else if (v.type() == typeid(float)) {
        return std::any_cast<float>(v);
    } else if (v.type() == typeid(double)) {
        return std::any_cast<double>(v);
    }

    return nullptr;
}

class MsgObject {
protected:
    static inline std::string selfSrc = "dev_dlt698";

    std::shared_ptr<MqttClient> _mqtt;
    std::shared_ptr<DeviceManager> _device;

    std::vector<std::string> split(const std::string &source, const std::string &s) {
        std::vector<std::string> result;

        std::string::size_type pos = 0;
        std::string::size_type prev = 0;

        while ((pos = source.find(s, prev)) != std::string::npos) {
            auto r = source.substr(prev, pos - prev);

            r.size() ? result.push_back(r) : (void)(nullptr);

            prev = pos + s.length();
        }
        auto r = source.substr(prev);
        r.size() ? result.push_back(r) : (void)(nullptr);

        return result;
    }

    /* pos 从 1 开始 */
    std::string subTopic(const std::string &topic, std::size_t pos) {
        auto res = split(topic, "/");
        if (pos > topic.length()) {
            return {};
        }

        return res[pos - 1];
    }

    bool isDisit(const std::string &s) const { return std::all_of(s.begin(), s.end(), ::isdigit); }

public:
    MsgObject() = default;
    MsgObject(std::shared_ptr<MqttClient> m, std::shared_ptr<DeviceManager> d) : _mqtt(m), _device(d) {}

public:
    virtual bool parse(const std::string &t, const std::string &payload) = 0;
    virtual MsgObject &action(void) = 0;
    virtual bool reply(void) = 0;
};
}; // namespace Protocol